/*
 * Copyright 2025 The JA-SIG Collaborative. All rights reserved.
 * distributed with this file and available online at
 */
package com.lap.auth.application.organization;

import com.lap.auth.application.organization.assembler.OrgAssembler;
import com.lap.auth.application.organization.command.CreateOrgCmd;
import com.lap.auth.application.organization.command.UpdateOrgCmd;
import com.lap.auth.application.organization.dto.GetOrgByIdsQuery;
import com.lap.auth.application.organization.dto.OrgNodeDto;
import com.lap.auth.application.organization.dto.OrgOptionDto;
import com.lap.auth.domain.organization.Organization;
import com.lap.auth.domain.organization.repository.OrgRepository;
import com.lap.auth.domain.organization.service.OrgValidator;
import com.lap.auth.shared.ports.SeqService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

/**
 * 组织架构应用服务层
 *
 * <ol>
 *   <li>不做业务规则，只做技术规则（加密/解密是技术实现，业务不关注）
 *   <li>取数，赋值，对象转换在这层执行
 *   <li>命名有规范，动词+领域名字
 *   <li>如查询比较多，建议分开领域QueryAppService,如:分页查询，分页查询返回关联字段
 * </ol>
 */
@RequiredArgsConstructor
@Service
public class OrgAppService {

  private final OrgAssembler orgAssembler;
  private final OrgValidator orgValidator;
  private final SeqService seqService;
  private final OrgRepository repository;

  public List<OrgNodeDto> getOrgTree() {
    List<Organization> allList = repository.findAll();
    List<OrgNodeDto> flatList = orgAssembler.toDtoList(allList);
    return orgAssembler.convertToTree(flatList);
  }

  public List<OrgOptionDto> queryOrgOptionByIds(GetOrgByIdsQuery query) {
    List<Organization> allList = repository.findByIds(query.getIdSet());
    return orgAssembler.toOptionDtoList(allList);
  }

  public Integer createOrg(CreateOrgCmd cmd) {
    String code = StringUtils.defaultIfBlank(cmd.getCode(), generateCode());
    Organization organization = orgAssembler.create(code, cmd);
    return repository.save(organization);
  }

  public Integer updateOrg(Integer id, UpdateOrgCmd cmd) {
    Organization old = orgValidator.assertOrgExists(id);
    String code = StringUtils.defaultIfBlank(old.getCode(), generateCode());
    Organization dept = orgAssembler.update(id, code, cmd);
    return repository.save(dept);
  }

  private String generateCode() {
    return seqService.getSeq("DEPT", false);
  }

  public Integer deleteOrg(Integer id) {
    Organization old = orgValidator.assertOrgExists(id);
    List<Organization> children = repository.findByPid(id);
    old.canDelete(children);
    return repository.deleteById(id);
  }
}
